﻿using System;
using Bintje.bintje; 
using System.Text;
using System.Collections.Generic;

namespace Bintje
{
    public class Trail : RepoObject
    {
        #region Fields

        private trail m_trail;
        private IList<Annotation> m_annotations;
        private string m_description;
        private string m_internalLayerList;
        private string m_internalWpList;
        private IList<Layer> m_layers;
        private string m_title;
        private int m_userId;
        private IList<WayPointWrapper> m_waypointsw;
        private IList<WayPoint> m_waypoints;
        private User m_user;
        private imageoSession m_session;
        private string m_latitude;
        private string m_longitude;
        private DateTime m_created;
        private bool m_createdSpecified;
        private long m_created1;
        private long m_modified;
        private long m_modified1;
        private DateTime m_trailCreated;
        private bool m_trailCreatedSpecified;
        private int m_firstwaipointId;
        private WayPointWrapper m_firstWaypoint;
        private bool m_enabled;
        private bool m_publicTrail;
        private int m_imageId;
        private string m_imageUrl;

        #endregion
        
        #region Properties

        public imageoSession Session
        {
            set { m_session = value; }
            get 
            {
                if (null == m_session)
                    m_session = System.Web.HttpContext.Current.Session["Session"] as imageoSession;
                return m_session;
            }
        }

        public IList<Annotation> Annotations
        {
            get { return m_annotations; }
            set { m_annotations = value; }
        }

        public string Description
        {
            get { return m_description; }
            set { m_description = value; }
        }

        public IList<Layer> Layers
        {
            get { return m_layers; }
            set { m_layers = value; }
        }

        public string Title
        {
            get { return m_title; }
            set { m_title = value; }
        }

        public IList<WayPointWrapper> WaypointsW
        {
            get { return m_waypointsw; }
            set { m_waypointsw = value; }
        }

        public IList<WayPoint> Waypoints
        {
            get { return m_waypoints; }
            set { m_waypoints = value; }
        }
        
        public User User
        {
            get { return m_user; }
            set { 
                m_user = value;
                m_userId = m_user.Id;
            }
        } 
        
        public int UserId
        {
            get { return m_userId; }
            set { m_userId = value; }
        }

        public string Latitude
        {
            get { return m_latitude; }
            //set { m_latitude = value; }
        }

        public string Longitude
        {
            get { return m_longitude; }
            //set { m_longitude = value; }
        }

        public long Created1
        {
            get { return m_created1; }
            set { m_created1 = value; }
        }

        public long Modified1
        {
            get { return m_modified1; }
            set { m_modified1 = value; }
        }

        public long Modified
        {
            get { return m_modified; }
            set { m_modified = value; }
        }
        
        public DateTime TrailCreated
        {
            get { return m_trailCreated; }
            set { m_trailCreated = value; }
        }

        public bool TrailCreatedSpecified
        {
            get { return m_trailCreatedSpecified; }
            set { m_trailCreatedSpecified = value; }
        }

        public int FirstwaipointId
        {
            get { return m_firstwaipointId; }
            set { m_firstwaipointId = value; }
        }

        public WayPointWrapper FirstWaypoint
        {
            get { return m_firstWaypoint; }
            set { m_firstWaypoint = value; }
        }

        public bool Enabled
        {
            get { return m_enabled; }
            set { m_enabled = value; }
        }

        public bool PublicTrail
        {
            get { return m_publicTrail; }
            set { m_publicTrail = value; }
        }

        public int ImageId
        {
            get { return m_imageId; }
            set { m_imageId = value; }
        }

        public string ImageUrl
        {
            get { return m_imageUrl; }
            set { m_imageUrl = value; }
        }

        #endregion

        #region ctor

        public Trail(int userId)
        {
            m_userId = userId;
        }

        public Trail(trailDB trailDB)
        {
            if (null != trailDB.annotations && trailDB.annotations.Length > 0)
            {
                m_annotations = new List<Annotation>();
                for (int i = 0; i < trailDB.annotations.Length; i++)
                {
                    m_annotations.Add(new Annotation(trailDB.annotations[i]));
                }
            }

            m_created = trailDB.created;
            m_createdSpecified = trailDB.createdSpecified;
            m_description = trailDB.description;
            m_id = trailDB.id;
            if (null != trailDB.firstWaypoint && null != trailDB.firstWaypoint.waypoint)
            {
                m_firstwaipointId = trailDB.firstWaypoint.waypoint.id;
                m_firstWaypoint = new WayPointWrapper(trailDB.firstWaypoint);
            }
            m_imageUrl = trailDB.imageUrl;

            if (null != trailDB.layers && trailDB.layers.Length > 0)
            {
                m_layers = new List<Layer>();
                for (int i = 0; i < trailDB.layers.Length; i++)
                {
                    m_layers.Add(new Layer(trailDB.layers[i]));
                }
            }

            m_latitude = trailDB.latitude;
            m_longitude = trailDB.longitude;
            m_publicTrail = trailDB.publicTrail;
            m_title = trailDB.title;
            if (null != trailDB.user)
            {
                m_userId = trailDB.user.id;
                m_user = new User(trailDB.user, string.Empty);
            }

            if (null != trailDB.waypoints && trailDB.waypoints.Length > 0)
            {
                m_waypointsw = new List<WayPointWrapper>();
                m_waypoints = new List<WayPoint>();
                for (int i = 0; i < trailDB.waypoints.Length; i++)
                {
                    m_waypointsw.Add(new WayPointWrapper(trailDB.waypoints[i]));
                    if (trailDB.waypoints[i].images != null && trailDB.waypoints[i].images.Length > 0)
                    {
                        string[] urls = (string[])Array.CreateInstance(typeof(string), trailDB.waypoints[i].images.Length);
                        for (int j = 0; j < trailDB.waypoints[i].images.Length; j++)
                        {
                            urls[j] = trailDB.waypoints[i].images[j].url;
                        }
                        m_waypoints.Add(new WayPoint(trailDB.waypoints[i].waypoint, urls));
                    }
                    else
                        m_waypoints.Add(new WayPoint(trailDB.waypoints[i].waypoint));
                    
                }
            }
        }

        public Trail(trail trail)
        {
            if (null != trail.annotations && trail.annotations.Length > 0)
            {
                m_annotations = new List<Annotation>();
                for (int i = 0; i < trail.annotations.Length; i++)
                {
                    m_annotations.Add(new Annotation(trail.annotations[i]));
                }
            }
            
            m_created1 = trail.created1;
            m_description = trail.description;
            m_enabled = trail.enabled;
            m_firstwaipointId = trail.firstWaypointId;
            m_id = trail.id;
            m_imageId = trail.imageId;
            m_internalLayerList = trail.internalLayerList;
            m_internalWpList = trail.internalWaypointIds;

            if (null != trail.layers && trail.layers.Length > 0)
            {
                m_layers = new List<Layer>();
                for (int i = 0; i < trail.layers.Length; i++)
                {
                    m_layers.Add(new Layer(trail.layers[i]));
                }
            }

            m_modified = trail.modified;
            m_modified1 = trail.modified1;
            m_publicTrail = trail.publicTrail;
            m_title = trail.title;
            m_userId = trail.userId;
            m_trailCreated = trail.trailCreated;
            m_trailCreatedSpecified = trail.trailCreatedSpecified;

            if (null != trail.waypoints && trail.waypoints.Length > 0)
            {
                m_waypoints = new List<WayPoint>();
                for (int i = 0; i < trail.waypoints.Length; i++)
                {
                    m_waypoints.Add(new WayPoint(trail.waypoints[i]));
                }
            }
        }
 
        #endregion

        #region Methods

        public static IList<Trail> Load(imageoSession session)
        {
            IList<Trail> result = new List<Trail>();
            if (session == null)
                return result;
            trailDBListResponse dbresp = API.instance.getMyTrails(session);
            if (null != dbresp && dbresp.status == API.RESPONSE_SUCCESS && null != dbresp.trailList)
            {
                for (int i = 0; i < dbresp.trailList.Length; i++)
                {
                    Trail trail = new Trail(dbresp.trailList[i]);
                    result.Add(trail);
                }
            }
            return result;
        }

        /// <summary>
        /// Loads all trails from the server
        /// </summary>
        /// <returns></returns>
        public static IList<Trail> LoadAll()
        {
            IList<Trail> result = new List<Trail>();
            trailDBListResponse dbresp = API.instance.getWorldTrails();
            if (null != dbresp && dbresp.status == API.RESPONSE_SUCCESS)
            {
                for (int i = 0; i < dbresp.trailList.Length; i++)
                {
                    Trail trail = new Trail(dbresp.trailList[i]);
                    result.Add(trail);
                }
            }
            return result;
        }

        public static IList<Trail> Search(string filter) 
        {
            IList<Trail> result = new List<Trail>();
            trailDBListResponse dbresp = API.instance.findTrails(filter);
            if (null != dbresp && dbresp.status == API.RESPONSE_SUCCESS)
            {
                for (int i = 0; i < dbresp.trailList.Length; i++)
                {
                    Trail trail = new Trail(dbresp.trailList[i]);
                    result.Add(trail);
                }
            }
            return result;
        }

        /*
        public static IList<Trail> SearchFull(TrailFilter filter)
        {
            IList<Trail> result = new List<Trail>();
            trailFilterRequest request = filter.ConvertToAPI();
            trailDBListResponse dbresp = API.instance.getFullTrails(request);
            if (null != dbresp && dbresp.status == API.RESPONSE_SUCCESS)
            {
                for (int i = 0; i < dbresp.trailList.Length; i++)
                {
                    Trail trail = new Trail(dbresp.trailList[i]);
                    result.Add(trail);
                }
            }
            return result;
        }
        */
        public static Trail Get(int trailID) 
        {
            trailRequest request = new trailRequest();
            request.trailId = trailID;
            try
            {
                trailResponse response = API.instance.getTrailDetails(request);
                if (null != response && response.status == API.RESPONSE_SUCCESS)
                {
                    Trail trail = new Trail(response.trailDB);
                    if (null != response.session)
                        trail.UserId = response.session.userId;
                    return trail;
                }
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public Trail Create()
        {
            trailRequest request = GetRequest();
            trailResponse response = API.instance.createTrail(request);
            if (null != response && response.status == API.RESPONSE_SUCCESS)
            {
                this.Id = response.trailId;
                return new Trail(response.trailDB);
            }
            return null;
        }

        public bool Delete()
        {
            trailRequest request = GetRequest();
            statusResponse response = API.instance.deleteTrail(request);
            if (null != response && response.status == API.RESPONSE_SUCCESS)
            {
                return true;
            }
            return false;
        }

        public Trail Update()
        {
            trailRequest request = GetRequest();
            trailResponse response = API.instance.editTrailData(request);
            try
            {
                if (null != response && response.status == API.RESPONSE_SUCCESS)
                {
                    return new Trail(response.trailDB);
                }
            }
            catch { }
            return null;
        }

        public Trail KeepImages(Trail trailToKeep) 
        {
            foreach (var wp in trailToKeep.Waypoints)
            {
                if (wp.Images == null && wp.ImageUrl != null)
                {
                    foreach (var url in wp.ImageUrl)
                    {
                        System.Text.RegularExpressions.Regex re =
                        new System.Text.RegularExpressions.Regex(@"id=\d+");
                        if (re.IsMatch(url))
                        {
                            string imgId = re.Match(url).Value.Replace("id=", string.Empty);
                            Bintje.Image img = new Bintje.Image();
                            img.Id = int.Parse(imgId);
                            wp.Images = new List<Bintje.Image>();
                            wp.Images.Add(img);
                        }
                    }
                }
            }
            return trailToKeep;
        }

        private trailRequest GetRequest() 
        {
            trail trail = ConvertToAPI();
            trailRequest request = new trailRequest();
            request.trail = trail;
            if (null != this.Session)
            {
                request.session = this.Session;
                request.trail.userId = this.Session.userId;
            }
            else if (null != this.User && null != this.User.Session)
            {
                request.session = this.User.Session;
                request.trail.userId = m_userId;
            }
            return request;
        }

        private trail ConvertToAPI()
        {
            trail trail = new trail();
            if (null != this.Annotations && this.Annotations.Count > 0)
            {
                trail.annotations = Annotation.ConvertToAPI(this.Annotations);
            }
            trail.created = m_trailCreated.ToBinary();
            trail.created1 = m_trailCreated.ToBinary();
            trail.description = this.Description;
            trail.enabled = m_enabled;
            trail.id = this.Id;
            trail.firstWaypointId = m_firstwaipointId;
            trail.internalLayerList = this.m_internalLayerList;
            trail.internalWaypointIds = this.m_internalWpList;
            if (null != this.Layers && this.Layers.Count > 0)
            {
                trail.layers = Layer.ConvertToAPI(this.Layers);
            }
            trail.imageId = m_imageId;
            if(!string.IsNullOrEmpty(m_internalLayerList))
                trail.internalLayerList = m_internalLayerList;
            if(!string.IsNullOrEmpty(m_internalWpList))
                trail.internalWaypointIds = m_internalWpList;
            trail.modified = m_modified1;
            trail.modified1 = m_modified1;
            trail.publicTrail = m_publicTrail;
            trail.title = this.Title;
            trail.trailCreated = m_trailCreated;
            trail.trailCreatedSpecified = m_trailCreatedSpecified;
            trail.userId = this.m_userId;
            if(null != this.Waypoints && this.Waypoints.Count > 0)
            {
                waypoint[] waypoints = (waypoint[])Array.CreateInstance(typeof(waypoint), this.Waypoints.Count);
                for (int i = 0; i < this.Waypoints.Count; i++)
                {
                    waypoints[i] = this.Waypoints[i].ConvertToAPI();
                }
                trail.waypoints = waypoints;
            }
            else if (null != this.WaypointsW && this.WaypointsW.Count > 0)
            {
                waypoint[] waypoints = (waypoint[])Array.CreateInstance(typeof(waypoint), this.WaypointsW.Count);
                for (int i = 0; i < this.WaypointsW.Count; i++)
                {
                    waypoints[i] = this.WaypointsW[i].WayPoint.ConvertToAPI();
                }
                trail.waypoints = waypoints;
            }
            return trail;
        }

        #endregion

    }
}
